/*****************************************
 * 功能：内存动态分配管理
 * Email：huiaove@126.com
 * Date：2020 12.25
 * Version：1.0.0.1
 * 修改记录：
 *             张亚辉    2020 12.25    修改自原子mymalloc
 * ***************************************/
#include "malloc.h"
/***************************************
 * 功能：内存复制
 * 参数：
 *         *des：目标地址
 *         *src：源地址
 *         n：复制长度
 * 返回：无
 * ************************************/
void mymemcpy(void *des, void *src, uint32_t n)
{
    uint8_t *xdes = des;
    uint8_t *xsrc = src;
    while (n--)
        *xdes++ = *xsrc++;
}
/**************************************
 * 功能：设置内存值
 * 参数：
 *         *des：内存地址
 *         value：设置的值
 *         count：内存大小
 * 返回：无
 * ***********************************/
void mymemset(void *des, uint8_t value, uint32_t count)
{
    uint8_t *xs = des;
    while (count--)
        *xs++ = value;
}

/*************************************
 * 功能：内存管理初始化
 * 参数：
 *         *m_dev:内存管理控制块
 *         *menbase:内存池基地址
 *         *men1mapbase:内存管理地址
 *         mem_size:内存池大小
 *         block_size:内存分块大小
 * 返回：无
 * **********************************/
void my_mem_init(Mallco_dev *m_dev, uint8_t *membase, uint16_t *mem1mapbase, uint32_t mem_size, uint32_t block_size)
{
    m_dev->memblksize = block_size;
    m_dev->memsize = mem_size;
    m_dev->memtblsize = mem_size / block_size;
    m_dev->membase = membase;
    m_dev->memmap = mem1mapbase;
    mymemset(m_dev->memmap, 0, m_dev->memtblsize * 2); //内存状态数据表清零
    mymemset(m_dev->membase, 0, m_dev->memsize);       //内存池所有数据清零
    m_dev->memrdy = 1;                                 //内存管理初始化
}
/***********************************
 * 功能：获取内存池使用率
 * 参数：
 *         *dev：内存管理控制块
 * 返回：无
 * *********************************/
uint8_t my_mem_perused(Mallco_dev *dev)
{
    uint32_t used = 0;
    uint32_t i;
    for (i = 0; i < dev->memtblsize; i++)
    {
        if (dev->memmap[i])
            used++;
    }
    return (used * 100) / (dev->memtblsize);
}
/************************************
 * 功能：内存分配（内部调用）
 * 参数：
 *         *dev：内存控制管理块
 *         size：分配的内存大小
 * 返回：
 *         0xFFFFFFFF:代表错误；其他值：内存偏移地址
 * **********************************/
uint32_t my_mem_malloc(Mallco_dev *dev, uint32_t size)
{
    signed long offset = 0;
    uint32_t nmemb;     //所需内存块数
    uint32_t cmemb = 0; //连续空内存块数
    uint32_t i;
    if (!dev->memrdy)
        return 0XFFFFFFFF; //内存管理控制块未初始化
    if (size == 0)
        return 0XFFFFFFFF;          //不需要分配
    nmemb = size / dev->memblksize; //计算需要分配的连续内存块数
    if (size % dev->memblksize)
        nmemb++;
    for (offset = dev->memtblsize - 1; offset >= 0; offset--) //搜索整个内存控制区
    {
        if (!dev->memmap[offset])
            cmemb++; //连续内存块增加
        else
            cmemb = 0;      //连续内存块清零
        if (cmemb == nmemb) //找到连续nmemb个空内存块
        {
            for (i = 0; i < nmemb; i++) //标注内存块非空
            {
                dev->memmap[offset + i] = nmemb;
            }
            return (offset * dev->memblksize); //返回偏移地址
        }
    }
    return 0XFFFFFFFF; //未成功分配到内存
}
/***************************************************
 * 功能：释放内存（内部调用）
 * 参数：
 *         *dev:内存控制管理块
 *         offset:内存地址
 * 返回：
 *         0：释放成功  1：释放失败
 * ************************************************/
uint8_t my_mem_free(Mallco_dev *dev, uint32_t offset)
{
    int i;
    if (!dev->memrdy) //内存管理块未初始化
    {
        return 1; //
    }
    if (offset < dev->memsize) //地址在内存池中
    {
        int index = offset / dev->memblksize; //偏移所在的内存块
        int nmemb = dev->memmap[index];       //内存块数量
        for (i = 0; i < nmemb; i++)           //内存块清零
        {
            dev->memmap[index + i] = 0;
        }
        return 0;
    }
    else
        return 2; //偏移超区
}
/***********************************************
 * 功能：释放内存（外部掉用）
 * 参数：
 *         *dev:内存控制管理块
 *         *prt:内存地址
 * 返回：无
 * ********************************************/
void myfree(Mallco_dev *dev, void *ptr)
{
    uint32_t offset;
    if (ptr == NULL)
        return; //地址为0
    offset = (uint32_t)ptr - (uint32_t)dev->membase;
    my_mem_free(dev, offset); //释放内存
}
/**********************************************
 * 功能：分配内存（外部调用）
 * 参数：
 *         *dev:内存控制管理块
 *         size:内存大小
 * 返回值：无
 * *******************************************/
void *mymalloc(Mallco_dev *dev, uint32_t size)
{
    uint32_t offset;
    offset = my_mem_malloc(dev, size);
    if (offset == 0XFFFFFFFF)
        return NULL;
    else
        return (void *)((uint32_t)dev->membase + offset);
}
/********************************************
 * 功能：重新分配内存（外部调用）
 * 参数：
 *         *dev：内存控制管理块
 *         *prt：旧内存地址
 *         size：要分配的内存大小
 * 返回：
 *         新分配到的内存地址
 * *****************************************/
void *myrealloc(Mallco_dev *dev, void *ptr, uint32_t size)
{
    uint32_t offset;
    offset = my_mem_malloc(dev, size);
    if (offset == 0XFFFFFFFF)
        return NULL;
    else
    {
        mymemcpy((void *)((uint32_t)dev->membase + offset), ptr, size); //拷贝旧内存内容到新内存
        myfree(dev, ptr);                                               //释放旧内存
        return (void *)((uint32_t)dev->membase + offset);               //返回新内存地址
    }
}

